﻿using System;
using System.Windows.Forms;
using DigitalRune.Windows.Docking;
using md.imi.membranes.gui.Editor;
using md.imi.membranes.gui.elements;
using md.imi.membranes.objects;
using md.imi.membranes.objects.membranes;

namespace md.imi.membranes.gui.Navigation
{
    public partial class CurrentConfigurationTree : DockableForm
    {
        private object mCurrentConfiguration;

        private enum Images
        {
            imgMembrane = 0,
            imgMultiset = 1,
            imgRule = 2
        }

        public CurrentConfigurationTree()
        {
            InitializeComponent();
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="membrane"></param>
        public void UpdateMembraneSelection(MembraneG sender, Membrane membrane)
        {
            SelectNodeByMembrane(treeNavigation.Nodes, membrane);
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="nodes"></param>
        /// <param name="membrane"></param>
        /// <returns></returns>
        private bool SelectNodeByMembrane(TreeNodeCollection nodes, Membrane membrane)
        {
            foreach (TreeNode node in nodes)
            {
                var nodeTagMembrane = node.Tag as Membrane;
                if (nodeTagMembrane != null && nodeTagMembrane.Id.Equals(membrane.Id))
                {
                    treeNavigation.SelectedNode = node;
                    node.Expand();
                    return true;
                }

                if (node.Nodes.Count > 0)
                {
                    if (SelectNodeByMembrane(node.Nodes, membrane))
                    {
                        return true;
                    }
                }
            }

            return false;
        }

        /// <summary>
        ///     List all membranes
        /// </summary>
        /// <param name="mebranesTree"></param>
        private void ListMembranes(MembranesTree mebranesTree, TreeNode parentNode)
        {
            
            foreach (var membrane in mebranesTree.Membranes)
            {
                var newNode = new TreeNode(membrane.Label)
                {
                    Tag = membrane,
                    ImageIndex = (int)Images.imgMembrane
                };

                if (parentNode != null)
                    parentNode.Nodes.Add(newNode);
                else
                    treeNavigation.Nodes.Add(newNode);

                DrawMembraneContent(newNode, membrane);

                if (membrane.Membranes != null && membrane.Membranes.Count > 0)
                {
                    ListMembranes(membrane, newNode);
                }
            }
        }

        /// <summary>
        ///     Add all membrane components to this node (multisets, rules, charge ... etc)
        /// </summary>
        /// <param name="newNode">Target node (parent node)</param>
        /// <param name="membrane">The membrane to analize</param>
        private void DrawMembraneContent(TreeNode newNode, MembranesTree membrane)
        {
            if (newNode == null || membrane == null)
            {
                return;
            }

            // draw charge

            // draw multisets
            if (membrane.Multiset != null)
            {
                foreach (var strObject in membrane.Multiset)
                {
                    newNode.Nodes.Add(strObject.ToString(), strObject.ToString(), (int)Images.imgMultiset);
                }
            }

            // draw rules
            if (membrane.Rules != null)
            {
                foreach (var rule in membrane.Rules)
                {
                    var ruleContent = rule.ToString();
                    newNode.Nodes.Add(ruleContent, ruleContent, (int)Images.imgRule);
                }
            }
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="eventArgs"></param>
        public void UpdatePsystemSelection(object sender, EventArgs eventArgs)
        {
            treeNavigation.Nodes.Clear();

            if (sender == null || !(sender is CurrentConfiguration))
            {
                return;
            }

            // update window info
            mCurrentConfiguration = sender;
            var form = sender as CurrentConfiguration;
            if (form.Project == null) return;

            var newNode = new TreeNode(form.Project.Membranes.Label)
            {
                Tag = form.Project.Membranes,
                ImageIndex = (int)Images.imgMembrane
            };
            
            DrawMembraneContent(newNode, form.Project.Membranes);
            treeNavigation.Nodes.Add(newNode);
            
            ListMembranes(form.Project.Membranes, newNode);
            TabText = String.Format("ConfigurationTree-{0}", form.Project.ProjectName);
        }

        private void treeNavigation_AfterSelect(object sender, TreeViewEventArgs e)
        {
            var membrane = (e.Node.Tag as MembranesTree);
            tbEdit.Enabled = (membrane != null);
            // tbEdit.Tag = membrane;

            if (membrane == null)
            {
                return;
            }

            // search selected PSystem
        }

        private void TollBarButtonsClick(object sender, EventArgs e)
        {
            var button = sender as ToolStripButton;
            var membrane = (treeNavigation.SelectedNode != null)
                               ? treeNavigation.SelectedNode.Tag as MembranesTree
                               : null;

            if (sender == null || membrane == null)
            {
                Console.WriteLine("Development error : cannot determine sender type or membrane is not selected");
                return;
            }

            if (button == tbEdit)
            {
                var membraneEditForm = new MembraneProperties();
                membraneEditForm.LoadData(membrane);

                if (membraneEditForm.ShowDialog() == DialogResult.OK)
                {
                    UpdatePsystemSelection(mCurrentConfiguration, null);
                    ((CurrentConfiguration) WorkSpace.Instance.SelectedProject.EditorForm).ReloadConfiguration(
                        WorkSpace.Instance.SelectedProject);
                }
            }
        }
    }
}